#include "common.h"
#include <iostream>
static SharedMemQueue* shmBob2Alice = nullptr;
static SharedMemQueue* shmAlice2Bob = nullptr;
constexpr time_t timeOutNs = 5000000000L;

void send(const Message *message)
{
    uint64_t producerIdx = shmBob2Alice->producer.load(std::memory_order_relaxed);
    uint64_t nextProducerIdx = (producerIdx + 1) % MAX_MESSAGE_CNT;
    // while (nextProducerIdx == shmBob2Alice->consumer.load(std::memory_order_acquire)) {
    //     // 等待消费者消费消息
    //     CPU_PAUSE();
    // }
    memcpy(&shmBob2Alice->msgBuffer[producerIdx], message, message->size);
    shmBob2Alice->producer.store(nextProducerIdx, std::memory_order_release);
    __builtin_prefetch(&shmBob2Alice->msgBuffer[nextProducerIdx], 1, 3);  // 预取写
}

const Message *recv()
{
    uint64_t consumerIdx = shmAlice2Bob->consumer.load(std::memory_order_relaxed);
    uint64_t nextConsumerIdx = (consumerIdx + 1) % MAX_MESSAGE_CNT;
    time_t startTime = now();
    while (consumerIdx == shmAlice2Bob->producer.load(std::memory_order_acquire)) {
        // 根据已有框架，可以确定通信结束是alice发完了数据后alice进程退出，bob进程不再收到数据
        // 所以设置个bob进程饿死超时值，为5s
        time_t curTime = now();
        if (curTime - startTime > timeOutNs) {
            // std::cout<<"startTime: "<<startTime<<", curTime: "<<curTime<<", timeOutNs: "<<timeOutNs<<"\n";
            // bob进程退出，由bob进程手动管理共享内存对象生命周期的结束，先解除映射再删除共享内存对象
            if (munmap(shmAlice2Bob, SHARED_MEM_SIZE) == -1) {
                perror("bob munmap failed");
            }
            if (munmap(shmBob2Alice, SHARED_MEM_SIZE) == -1) {
                perror("bob munmap failed");
            }
            if (shm_unlink(SHAREDMEM_NAME_B2A) == -1) {
                perror(SHAREDMEM_NAME_B2A);
            }
            if (shm_unlink(SHAREDMEM_NAME_A2B) == -1) {
                perror(SHAREDMEM_NAME_A2B);
            }
            printf("no message remained, bob exit\n");
            exit(0);
        }
        // 等待生产者生产消息
        CPU_PAUSE();
    }
    shmAlice2Bob->consumer.store(nextConsumerIdx, std::memory_order_release);
     // 预取读取，将数据预取到cpu缓存中，不应该是payload，应该是checksum、size，而且未来只读一次。第一个参数表示预取的地址，第二个参数表示读(0)还是写(1)，第三个参数表示这个数据时间局部性(0表示使用1次，3表示使用多次)
    // __builtin_prefetch(shmAlice2Bob->msgBuffer[consumerIdx].payload, 0, 3);
    __builtin_prefetch(&(shmAlice2Bob->msgBuffer[consumerIdx].checksum), 0, 0);
    __builtin_prefetch(&(shmAlice2Bob->msgBuffer[consumerIdx].size), 0, 0);
    return &shmAlice2Bob->msgBuffer[consumerIdx];
}


int main()
{
    // 获取共享内存，映射到地址空间，共享内存对象由bob进程负责创建
    while (!shmAlice2Bob && !shmBob2Alice) {
        shmAlice2Bob = GetAndMapShm(SHAREDMEM_NAME_A2B, true);
        shmBob2Alice = GetAndMapShm(SHAREDMEM_NAME_B2A, true);
        sleep(1);
    }
    // Bob绑定CPU core
    cpu_set_t cpuSet;
    BindCpuCore(cpuSet, 1);
    // 打印当前CPU core
    printf("Bob: Current CPU core: %d\n", sched_getcpu());
    // static Message *m2 = (Message *)aligned_alloc(64, MESSAGE_SIZES[4]);
    Message *m2 = (Message *)malloc(MESSAGE_SIZES[4]);
    while (true)
    {
        const Message *m1 = recv();
        assert(m1->checksum == crc32(m1));
        // 这里尝试过m2 = const_cast<Message*>(m1)，但是实测却性能不佳
        memcpy(m2, m1, m1->size); // 拷贝m1至m2
        m2->payload[0]++;         // 第一个字符加一
        m2->checksum = crc32(m2); // 更新校验和
        send(m2);
    }
    return 0;
}